﻿/*****************************************************
**Copyright(C), 2021-2022, Ciqtek Technology.
**Version:     1.0
**Author:      hujr
**Date:        2021/12/01
**Description: 抓图预览控件
*****************************************************/

#ifndef SNAPIMGVIEW_H
#define SNAPIMGVIEW_H

#include "../../ofuidll_global.h"

#include "SnapImgDef.h"
#include "SnapImgItem.h"
#include "SnapGroupView.h"
#include "SnapImgItemDelegate.h"

#include <QWidget>
#include <QStackedWidget>
#include <QScrollArea>
#include <QScrollBar>
#include <QVBoxLayout>

namespace OfUI {

	class OFUIDLL_EXPORT SnapImgView : public QWidget
	{
		Q_OBJECT

	public:
		explicit SnapImgView(QWidget *parent = nullptr);
		~SnapImgView();

	public:
		/**
		 * @brief  setItemDelegate 设置创建SnapImgItem委托
		 * @param  *
		 * @return void
		 */
		void setItemDelegate(SnapImgItemDelegate*);

		/**
		 * @brief  getItemDelegate 获取创建SnapImgItem委托
		 * @return SnapImgItemDelegate*
		 */
		SnapImgItemDelegate* getItemDelegate();

		/**
		 * @brief  setGroupType 设置数据分组类型
		 * @param  &
		 * @return void
		 */
		void setGroupType(const GroupType&);

		/**
		 * @brief  getGroupType 获取数据分组类型
		 * @return GroupType
		 */
		GroupType getGroupType() const;

		/**
		 * @brief  setShowItemPath 设置数据项是否显示底部区域
		 * @param
		 * @return void
		 */
		void setShowItemPath(bool);

		/**
		 * @brief  isShowItemPath 获取数据项是否显示文本
		 * @return bool
		 */
		bool isShowItemPath() const;

		/**
		 * @brief  spiltDataToGroup 数据分组
		 * @param  dataList
		 * @return QList<SnapDataGroup>
		 */
		QList<SnapDataGroup> spiltDataToGroup(const QList<SnapData>& dataList);

		/**
		 * @brief  updateSnapData 刷新数据项（删除原来数据项）
		 * @param  dataList
		 * @return void
		 */
		void updateSnapData(const QList<SnapData>& dataList);

		/**
		 * @brief  updateSnapDataGroup 刷新数据组（删除原来数据项）
		 * @param  dataList
		 * @return void
		 */
		void updateSnapDataGroup(const QList<SnapDataGroup>& groupList);

		/**
		 * @brief  insertSnapData 插入数据项（追加新数据）
		 * @param  dataList
		 * @return void
		 */
		void insertSnapData(const QList<SnapData>& dataList);

		/**
		 * @brief  insertSnapDataGroup 插入数据组（追加新数据）
		 * @param  groupList
		 * @return void
		 */
		void insertSnapDataGroup(const QList<SnapDataGroup>& groupList);

		/**
		 * @brief  deleteSnapDataById 通过Id删除数据项
		 * @param  &
		 * @return void
		 */
		void deleteSnapDataById(const int&);

		/**
		 * @brief  replaceOneSnapData 替换Item数据
		 * @param  oldData
		 * @param  newData
		 * @return bool
		 */
		bool replaceOneSnapData(const SnapData& oldData, const SnapData& newData);

		/**
		 * @brief  getSelectData 获取所有选中数据项
		 * @return const QList<SnapData>&
		 */
		const QList<SnapData>& getSelectData() const;

		/**
		 * @brief  setSelectData 设置选中数据项
		 * @param  &
		 * @return void
		 */
		void setSelectData(const QList<SnapData>&);

		/**
		 * @brief  setSelectData 设置选中数据项
		 * @param  &
		 * @return void
		 */
		void setSelectData(const SnapData&);

		/**
		 * @brief  setMaxZoomLimit 设置Item缩放的最大比例限制[1.0-2.0]
		 * @param  fRatio
		 * @return void
		 */
		void setMaxZoomLimit(float fRatio);

		/**
		 * @brief  getMaxZoomLimit 获取Item缩放的最大比例限制[1.0-2.0]
		 * @return float
		 */
		float getMaxZoomLimit() const;

		/**
		 * @brief  setMinZoomLimit 设置Item缩放的最小比例限制[0.1-1.0]
		 * @param  fRatio
		 * @return void
		 */
		void setMinZoomLimit(float fRatio);

		/**
		 * @brief  getMinZoomLimit 获取Item缩放的最大比例限制[0.1-1.0]
		 * @return float
		 */
		float getMinZoomLimit() const;

		/**
		 * @brief  setScrollBarValue 设置滚动条的当前值
		 * @param  nValue
		 * @return void
		 */
		void setScrollBarValue(int nValue);

		/**
		 * @brief  getAllSnapData  获取当前时刻所有Item数据，按照Item布局从上到下，从左到右排序
		 * @return QT_NAMESPACE::QList<SnapData>
		 */
		QList<SnapData> getAllSnapData();

	Q_SIGNALS:
		/**
		 * @brief  signalItemSelectsChanged	    Item选中项变化时通知信号
		 * @param  dataList						当前所有选中Item的数据，数据按选中顺序排序，末尾数据是最后选中的。也可以通过 getSelectsData() 获取。
		 * @return void
		 */
		void signalItemSelectsChanged(const QList<SnapData>& dataList);

		/**
		 * @brief  signalItemContextMenu	    Item右键菜单信号
		 * @param  data						    触发信号的Item 数据
		 * @param  globalPos				    鼠标点击时的全局位置
		 * @return void
		 */
		void signalItemContextMenu(const SnapData& data, QPoint globalPos);

		/**
		 * @brief  signalItemCustomMsg          自定义信号，方便SnapImgItem派生类使用
		 * @param  data		                    Item 数据
		 * @param  msg		                    自定义消息
		 * @return void
		 */
		void signalItemCustomMsg(const SnapData& data, const QVariant& msg);

		/**
		 * @brief  signal_scrollBarValueChanged 滚动条value变化信号
		 * @param  nValue		                当前值
		 * @param  nMinValue	                最小值
		 * @param  nMaxValue	                最大值
		 * @return void
		 */
		void signalScrollBarValueChanged(int nValue, int nMinValue, int nMaxValue);

	protected:
		/**
		 * @brief  eventFilter 事件过滤器
		 * @param  watched
		 * @param  event
		 * @return bool
		 */
		bool eventFilter(QObject *watched, QEvent *event);

		/**
		 * @brief  resizeEvent 大小变化事件
		 * @param  event
		 * @return void
		 */
		void resizeEvent(QResizeEvent *event);

	private:
		/**
		 * @brief  init  初始化
		 * @return void
		 */
		void init();

		/**
		 * @brief  creatUI  动态生成界面
		 * @return void
		 */
		void creatUI();

		/**
		 * @brief  resetSelectState 重置所有Item选中状态
		 * @return void
		 */
		void resetSelectState();

		/**
		 * @brief  updateSelectState 更新所有Item已选中状态
		 * @return void
		 */
		void updateSelectState();

		/**
		 * @brief  createSnapGroupView 创建组窗口
		 * @return SnapGroupView*
		 */
		SnapGroupView* createSnapGroupView();

		/**
		 * @brief  findGroupViewByTime 通过Time查找组
		 * @param  &
		 * @return SnapGroupView*
		 */
		SnapGroupView* findGroupViewByTime(const quint64&);

		/**
		 * @brief  findSnapItemById 通过Id查找Item
		 * @param  &
		 * @return SnapImgItem*
		 */
		SnapImgItem* findSnapItemById(const int&);

		/**
		 * @brief  appendToSelelctList 添加选中数据到选中列表尾部
		 * @param  &
		 * @return void
		 */
		void appendToSelelctList(const SnapData&);

		/**
		 * @brief  deleteFromSelectList 通过Id从选中列表删除选中数据
		 * @param  nId
		 * @return bool
		 */
		bool deleteFromSelectList(const int& nId);

		/**
		 * @brief  pushItemToCache 将多余的Item放到缓存中去
		 * @param  *
		 * @return void
		 */
		void pushItemToCache(SnapImgItem*);

		/**
		 * @brief  pullItemFromCache 从缓存中拿出Item
		 * @return SnapImgItem*
		 */
		SnapImgItem* pullItemFromCache();

		/**
		 * @brief  clearItemCache 清除Item缓存
		 * @return void
		 */
		void clearItemCache();

		/**
		 * @brief  setItemZoomIn Item放大操作
		 * @return void
		 */
		void setItemZoomIn();

		/**
		 * @brief  setItemZoomOut Item缩小操作
		 * @return void
		 */
		void setItemZoomOut();

	private:
		/** 数据分组类型
		 */
		GroupType m_eGroupType;

		/** 日期格式
		 */
		QString m_strDateTimeFmt;

		/** 是否显示路径
		 */
		bool m_bShowItemPath;

		/** 创建Item 委托
		 */
		SnapImgItemDelegate* m_pSnapItemDelegate;

		/** Item 缓存列表
		 */
		QList<SnapImgItem*> m_cacheItemList;

		/** Item 选中项数据列表
		 */
		QList<SnapData> m_selectedItemsData;

		/** 基于正常大小的最小缩放比例 [0.1 - 1.0]
		 */
		float m_fMinZoomLimit;

		/** 基于正常大小的最大缩放比例 [1.0 - 2.0]
		 */
		float m_fMaxZoomLimit;

		/** 当前缩放比例，默认 1.0
		 */
		float m_fCurrentZoom;

		/** 缩放速度, 默认0.1
		 */
		float m_fZoomSpeed;

		/** 滚动区域
		 */
		QScrollArea *m_pScrollArea;

		/** 滚动区域中心窗口
		 */
		QWidget *m_pScrollAreaWidgetContents;

		/** Group 纵向布局
		 */
		QVBoxLayout *m_pVLayout;
	};

}

#endif // SNAPIMGVIEW_H